﻿/*
 * ListPlus
 * 
 * initial implementation : 1.5.2011
 *
 * Copyright (c) Adam Sida, asida@centrum.cz.
 * All rights reserved.
 * 
 * for license see Petra.Gis.License.txt
 */
using System;
using System.Collections;
using System.Collections.Generic;


namespace Petra.Gis.RenderingServices.PlanarBase.Support
{


  /// <summary>
  /// represents readonly enumerable List of <c>T</c>
  /// !!!! this class must inherit from IList<T> not from List<T> !!!
  /// reason is that add, remove, insert methods can't be overriden in System.Collections.GenericList<T> !!!
  /// this is workaround.  /// </summary>
  public abstract class ListPlus<T> : KeepRelationWith<LegendNodeBase>, IList<T>
  {


    private IList<T> _items;


    protected ListPlus()
    {
      _items = new List<T>();
      this.IsReadOnly = false;
    }




    protected ListPlus(IList<T> storage)
    {
      if (storage == null)
        throw new ArgumentNullException();

      this.IsReadOnly = storage.IsReadOnly;

      _items = storage;
    }






    /// <summary>
    /// Adds an item to the end of the item list
    /// </summary>
    /// <param name="item">The item to be added to the end of the list</param>
    public virtual void Add(T newChild)
    {
      if (IsReadOnly)
        throw new InvalidOperationException();

      _items.Add(newChild);
    }





    /// <summary>
    /// Removes all elements from the list
    /// </summary>
    public virtual void Clear()
    {
      if (IsReadOnly)
        throw new InvalidOperationException();

      _items.Clear();
    }





    /// <summary>
    /// Determines whether an element is in the list
    /// </summary>
    /// <param name="item">The object to locate in the list.
    /// </param>
    /// <returns>true if item is found in the list, otherwise false.</returns>
    public virtual bool Contains(T item)
    {
      return _items.Contains(item);
    }




    /// <summary>
    /// indicates whether list is readonly.
    /// </summary>
    public virtual bool IsReadOnly
    { get; protected set; }





    /// <summary>
    /// Removes the first occurrence of a specific item from the list
    /// </summary>
    /// <param name="item">The item to remove from the list.</param>
    /// <returns>true if item is successfully removed, otherwise false.
    /// This method also returns false if item was not found in the list</returns>
    public virtual bool Remove(T item)
    {
      if (IsReadOnly)
        throw new InvalidOperationException();

      return _items.Remove(item);
    }






    /// <summary>
    /// Removes the element at the specified index of the list.
    /// </summary>
    /// <param name="index">The zero-based index of the element to remove.</param>
    public virtual void RemoveAt(int index)
    {
      if (IsReadOnly)
        throw new InvalidOperationException();
      
      _items.RemoveAt(index);
    }





    /// <summary>
    /// Gets the number of elements actually contained in the list
    /// </summary>
    public virtual int Count
    {
      get { return _items.Count; }
    }






    /// <summary>
    /// Copies the elements of the list 
    /// to an System.Array, starting at a particular System.Array index.
    /// </summary>
    /// <param name="array">The one-dimensional System.Array that is the destination
    /// of the elements copied from System.Collections.ICollection.
    /// The System.Array must have zero-based indexing.</param>
    /// <param name="arrayIndex">The zero-based index in array at which copying begins.</param>
    public virtual void CopyTo(T[] array, int arrayIndex)
    {
      _items.CopyTo(array, arrayIndex);
    }





    /// <summary>
    /// Returns an enumerator that iterates through the list
    /// </summary>
    /// <returns>An enumerator for the list.</returns>
    public virtual IEnumerator<T> GetEnumerator()
    {
      return _items.GetEnumerator();
    }





    IEnumerator IEnumerable.GetEnumerator()
    {
      return GetEnumerator();
    }






    /// <summary>
    /// Gets or sets the element at the specified index.
    /// </summary>
    /// <param name="index">The zero-based index of the element to get or set.</param>
    /// <returns>The item at the specified index.</returns>
    public virtual T this[int index]
    {
      get { return _items[index]; }
      set 
      {
        if (IsReadOnly)
          throw new InvalidOperationException();

        _items[index] = value; 
      }
    }





    /// <summary>
    /// Searches for the specified object and returns the zero-based index
    /// of the first occurrence within the entire list.
    /// </summary>
    /// <param name="item"> The item to locate in the list</param>
    /// <returns>The zero-based index of the first occurrence of item
    /// within the entire list.</returns>
    public virtual int IndexOf(T item)
    {
      return _items.IndexOf(item);
    }






    /// <summary>
    /// Inserts an item into the list at the specified index.
    /// </summary>
    /// <param name="index">The zero-based index at which item should be inserted.</param>
    /// <param name="item">The item to insert.</param>
    public virtual void Insert(int index, T item)
    {
      if (IsReadOnly)
        throw new InvalidOperationException();

      _items.Insert(index, item);
    }



  }

}
